Java
Programming Guidelines
Copyright ⌐ 1999 Scott Ambler, Ambysoft, Inc.
The Java Coding Guidelines are provided under license from Scott Ambler,
Ambysoft Inc., www.ambysoft.com.
They have been reformatted for inclusion in the Rational Unified Process.
- Introduction
- Classification of Guidelines
- Coding Standards
- Naming conventions
- Documentation conventions
- Types of Java comments
- A quick overview of javadoc
- Standards for
member functions
- Naming member functions
- Naming accessor member
functions
- Getters
- Setters
- Naming Constructors
- Member function visibility
- Documenting member functions
- Techniques for writing
clean code
- Standards for
fields/properties
- Naming fields
- Naming components
- Naming constants
- Naming collections
- Field visibility
- Documenting a field
- Using accessor member
functions
- Why use accessors?
- Naming accessors
- Accessors for constants
- Accessors for collections
- Accessing
several fields simultaneously
- Visibility of accessors
- Standards for local variables
- Naming local variables
- Naming streams
- Naming loop counters
- Naming exception objects
- Declaring and
documenting local variables
- Standards for
parameters to member functions
- Naming parameters
- Documenting parameters
- Standards
for classes, interfaces, packages and compilation units
- Standards for classes
- Naming classes
- Documenting a class
- Class declarations
- Minimize
the public and protected interface
- Standards for interfaces
- Naming interfaces
- Documenting interfaces
- Standards for packages
- Naming packages
- Documenting packages
- Standards for compilation
units
- Naming compilations units
- Documenting compilation
units
- Error handling and
exceptions
- Miscellaneous standards and issues
- Reuse
- Importing classes
- Optimizing Java code
- Writing Java test harnesses
- Patterns of success
- Summary
- Java naming conventions
- Java documentation
conventions
- Java comment types
- What to document
- Java coding conventions
(general)
- References
- Glossary
This document describes a collection of standards,
conventions, and guidelines for writing solid Java code. They are based on
sound, proven software engineering principles that lead to code that is easy to
understand, to maintain, and to enhance. Furthermore, by following these coding
standards your productivity as a Java developer should increase remarkably.
Experience shows that by taking the time to write high-quality code right from
the start you will have a much easier time modifying it during the development
process. Finally, following a common set of coding standards leads to greater
consistency, making teams of developers significantly more productive.
The First and Last Guideline:
Use common sense. When you cannot find a rule or
guideline, when the rule obviously does not apply, when everything else fails:
use common sense, and check the fundamental principles. This rule overrides
all of the others. Common sense is required.
Coding standards for Java are important because they lead to
greater consistency within your code and the code of your teammates. Greater
consistency leads to code that is easier to understand, which in turn means it
is easier to develop and to maintain. This reduces the overall cost of the
applications that you create.
You have to remember that your Java code will exist for a long time, long
after you have moved on to other projects. An important goal during
development is to ensure that you can transition your work to another
developer, or to another team of developers, so that they can continue to
maintain and enhance your work without having to invest an unreasonable effort
to understand your code. Code that is difficult to understand runs the risk of
being scrapped and rewritten.
We will be discussing naming conventions throughout the
standards, so let. s set the stage with a few basics:
- Use full English descriptors that accurately describe the
variable/field/class/& For example, use names like firstName,
grandTotal, or CorporateCustomer. Although names like x1,
y1, or fn are easy to type because they. re short, they do not
provide any indication of what they represent and result in code that is
difficult to understand, maintain, and enhance.
- Use terminology applicable to the domain. If your users refer to
their clients as customers, then use the term Customer for the class,
not Client. Many developers will make the mistake of creating generic
terms for concepts when perfectly good terms already exist in the
industry/domain.
- Use mixed case to make names readable. You should use lower case
letters in general, but capitalize the first letter of class names and
interface names, as well as the first letter of any non-initial word [KAN97].
- Use abbreviations sparingly, but if you do so then use them
intelligently. This means you should maintain a list of standard short
forms (abbreviations), you should choose them wisely, and you should use
them consistently. For example, if you want to use a short form for the word
"number," then choose one of nbr, no, or num,
document which one you chose (it does not really matter which one), and use
only that one.
- Avoid long names (< 15 characters is a good idea). Although the
class name PhysicalOrVirtualProductOrService might seem to be a good
class name at the time this name is simply too long and you should consider
renaming it to something shorter, perhaps something like Offering.
- Avoid names that are similar or differ only in case. For example,
the variable names persistentObject and persistentObjects
should not be used together, nor should anSqlDatabase and anSQLDatabase.
- Avoid leading or trailing underscores. Names with leading or
trailing underscores are usually reserved for system purposes, and may not
be used for any user-created names except for pre-processor defines. More
importantly, underscores are annoying and difficult to type so try to avoid
their use whenever possible.
We will also be discussing documentation conventions, so
let. s discuss some of the basics first:
- Comments should add to the clarity of your code. The reason why you
document your code is to make it more understandable to you, your coworkers,
and to any other developer who comes after you.
- If your program is not worth documenting, it probably is not worth
running [NAG95]
- Avoid decoration, i.e. do not use banner-like comments. In the 1960s
and 1970s COBOL programmers got into the habit of drawing boxes, typically
with asterisks, around their internal comments. Sure, it gave them an outlet
for their artistic urges, but frankly it was a major waste of time that
added little value to the end product. You want to write clean code, not
pretty code. Furthermore, because many of the fonts used to display and
print your code are proportional, and many are not, you can. t line up your
boxes properly anyway.
- Keep comments simple. Some of the best comments are simple,
point-form notes. You do not have to write a book, you just have to provide
enough information so that others can understand your code.
- Write the documentation before you write the code. The best way to
document code is to write the comments before you write the code. This gives
you an opportunity to think about how the code will work before you write it
and will ensure that the documentation gets written. Alternatively, you
should at least document your code as you write it. Because documentation
makes your code easier to understand you are able to take advantage of this
fact while you are developing it. If you are going to invest the time
writing documentation you should at least get something out of It [AMB98].
- Document why something is being done, not just what. For example,
the code in Example 1 below shows that a 5% discount is being given on
orders of $1,000 dollars or more. Why is this being done? Is there a
business rule that says that large orders get a discount? Is there a
limited-time special on large orders or is it a permanent program? Was the
original programmer just being generous? You do not know unless it is
documented somewhere, either in the source code itself or in an external
document.
Example
1.1
if ( grandTotal >= 1000.00)
{
grandTotal = grandTotal * 0.95;
}
Java has three styles of comments: Documentation comments
start with /** and end with */, C-style comments which start with /* and end
with */, and single-line comments that start with // and go until the end of
the source-code line. In the chart below is a summary of a suggested
use for each type of comment, as well as several examples.
Comment Type |
Usage |
Example |
Documentation |
Use documentation comments
immediately before declarations of interfaces, classes, member
functions, and fields to document them. Documentation comments are
processed by javadoc, see below, to create external
documentation for a class. |
/**
Customer . A customer is any person or organization that we sell
services and products to.
@author S.W. Ambler
*/ |
C style |
Use C-style comments to
document out lines of code that are no longer applicable, but that you
want to keep just in case your users change their minds, or because
you want to temporarily turn it off while debugging. |
/*
This code was commented out by B. Gustafsson on June 4, 1999
because it was replaced by the preceding code. Delete it after two
years if it is still not applicable.
. . . (the source code )
*/ |
Single line |
Use single line comments
internally within member functions to document business logic,
sections of code, and declarations of temporary variables. |
// Apply a 5% discount to
all
// invoices over $1000 due to
// generosity campaign started in
// Feb. of 1995. |
The important thing is that your organization should set a standard as to
how C-style comments and single-line comments are to be used, and then to
follow that standard consistently. Use one type to document business logic
and use the other to document out old code. Use single-line comments for
business logic because you can put the documentation on the same line as the
code (this is called inlining). Use C-style comments for documenting out old
code because that allows you to comment out several lines at once. Because
C-style looks very similar to documentation comments don't use them
elsewhere so as to avoid confusion.
Beware Endline Comments [MCO93]
argues strongly against the use of inline comments, also known as endline
comments or end of line comments. He points out that the comments have to be
aligned to the right of the code so that they do not interfere with the
visual structure of the code. As a result they tend to be hard to format,
and that "if you use many of them, it takes time to align them. Such
time is not spent learning more about the code; it is dedicated solely to
the tedious task of pressing the spacebar or the tab key." He also
points out that endline comments are also hard to maintain because when the
code on the line grows it bumps the endline comment out, and that if you are
aligning them you have to do the same for the rest of them.
Included in Sun. s Java Development Kit (JDK) is a program
called javadoc that processes Java code files and produces external
documentation, in the form of HTML files, for your Java programs. Javadoc
supports a limited number of tags, reserved words that mark the beginning of
a documentation section. Please refer to the JDK javadoc
documentation for further details.
Tag |
Used for |
Purpose |
@author name |
Classes,
Interfaces |
Indicates the author(s) of a
given piece of code. One tag per author should be used. |
@deprecated |
Classes,
Member Functions |
Indicates that the API for
the class& has been deprecated and therefore should not be used any
more. |
@exception name description |
Member Functions |
Describes the exceptions
that a member function throws. You should use one tag per exception and
give the full class name for the exception. |
@param name description |
Member Functions |
Used to describe a parameter
passed to a member function, including its type/class and its usage. Use
one tag per parameter. |
@return description |
Member Functions |
Describes the return value,
if any, of a member function. You should indicate the type/class and the
potential use(s) of the return value. |
@since |
Classes, Member Functions |
Indicates how long the item
has existed, i.e. since JDK 1.1 |
@see ClassName |
Classes, Interfaces, Member
Functions, Fields |
Generates a hypertext link
in the documentation to the specified class. You can, and probably
should, use a fully qualified class name. |
@see ClassName#member
functionName |
Classes, Interfaces, Member
Functions, Fields |
Generates a hypertext link
in the documentation to the specified member function. You can, and
probably should, use a fully qualified class name. |
@version text |
Classes, Interfaces |
Indicates the version
information for a given piece of code. |
The way that you document your code has a huge impact both on your own
productivity and on the productivity of everyone else who later maintains
and enhances it. By documenting your code early in the development process
you become more productive because it forces you to think through your logic
before you commit it to code. Furthermore, when you revisit code that you
wrote days or weeks earlier you can easily determine what you were thinking
when you wrote it . it is documented for you already.
Never forget that the code that you write today may still be
in use many years from now and will likely be maintained and enhanced by
somebody other than you. You must strive to make your code as "clean"
and understandable as possible, because these factors make it easier to maintain
and to enhance.
Member Functions should be named using a full English
description, using mixed case with the first letter of any non-initial word
capitalized. It is also common practice for the first word of a member
function name to be a strong, active verb.
Examples:
openAccount()
printMailingLabel()
save()
delete()
This convention results in member functions whose purpose can often be
determined just by looking at its name. Although this convention results in a
little extra typing by the developer, because it often results in longer
names, this is more than made up for by the increased understandability of
your code.
We will discuss accessors, member functions that get and set
the values of fields (fields/properties) in greater detail in a following
chapter. The naming conventions for accessors, however, are summarized below.
Getters are member functions that return the value of a
field. You should prefix the word . get. to the name of the field, unless it
is a boolean field and then you prefix . is. to the name of the field
instead of . get..
Examples:
getFirstName()
getAccountNumber()
isPersistent()
isAtEnd()
By following this naming convention you make it obvious that a member
function returns a field of an object, and for boolean getters you make it
obvious that it returns true or false. Another advantage of this standard is
that it follows the naming conventions used by the beans development kit
(BDK) for getter member functions [DES97]. The main
disadvantage is that . get. is superfluous, requiring extra typing.
Alternative Naming Convention for Getters . Has and Can
A viable alternative, based on proper English conventions,
is to use the prefix . has. or . can. instead of . is. for boolean getters.
For example, getter names such as hasDependents() and canPrint()
make a lot of sense when you are reading the code. The problem with this
approach is that the BDK will not pick up on this naming strategy (yet). You
could rename these member functions isBurdenedWithDependents() and isPrintable().
Setters, also known as mutators, are member functions that
modify the values of a field. You should prefix the word . set. to the name
of the field, regardless of the field type.
Examples:
setFirstName(String aName)
setAccountNumber(int anAccountNumber)
setReasonableGoals(Vector newGoals)
setPersistent(boolean isPersistent)
setAtEnd(boolean isAtEnd)
Following this naming convention you make it obvious that a member
function sets the value of a field of an object. Another advantage of this
standard is that it follows the naming conventions used by the beans
development kit (BDK) for setter member functions [DES97].
The main disadvantage is that . set. is superfluous, requiring extra typing.
Constructors are member functions that perform any necessary
initialization when an object is first created. Constructors are always given
the same name as their class. For example, a constructor for the class Customer
would be Customer(). Note that the same case is used.
Examples:
Customer()
SavingsAccount()
PersistenceBroker()
This naming convention is set by Sun and must be strictly adhered to.
For a good design where you minimize the coupling between
classes, the general rule of thumb is to be as restrictive as possible when
setting the visibility of a member function. If a member function does not
have to be public then make it protected, and if it does not have to be
protected then make it private.
Visibility |
Description |
Proper Usage |
public |
A public member function can
be invoked by any other member function in any other object or class. |
When the member function must
be accessible by objects and classes outside of the class hierarchy in
which the member function is defined. |
protected |
A protected member function
can be invoked by any member function in the class in which it is defined
or any subclasses of that class. |
When the member function
provides behavior that is needed internally within the class hierarchy but
not externally. |
private |
A private member function can
only be invoked by other member functions in the class in which it is
defined, but not in the subclasses. |
When the member function
provides behavior that is specific to the class. Private member functions
are often the result of refactoring, also known as reorganizing, the
behavior of other member functions within the class to encapsulate one
specific behavior. |
The manner in which you document a member function will often be the
deciding factor as to whether or not it is understandable, and therefore
maintainable and extensible.
The Member Function Header
Every Java member function should include some sort of
header, called member function documentation, at the top of the source code
that documents all of the information that is critical to understanding it.
This information includes, but is not limited to the following:
- What and why the member function does what it does. By documenting
what a member function does you make it easier for others to determine if
they can reuse your code. Documenting why it does something makes it
easier for others to put your code into context. You also make it easier
for others to determine whether or not a new change should actually be
made to a piece of code (perhaps the reason for the new change conflicts
with the reason why the code was written in the first place).
- What a member function must be passed as parameters. You also need
to indicate what parameters, if any, must be passed to a member function
and how they will be used. This information is needed so that other
programmers know what information to pass to a member function. javadoc
@param tag, discussed in (section 1.4.2 "A Quick Overview of
javadoc"), is used for this.
- What a member function returns. You need to document what, if
anything, a member function returns so that other programmers can use the
return value/object appropriately. The javadoc @return tag,
discussed in (section 1.4.2 "A Quick Overview of javadoc"), is
used for this.
- Known bugs. Any outstanding problems with a member function should
be documented so that other developers understand the
weaknesses/difficulties with the member function. If a given bug is
applicable to more than one member function within a class, then it should
be documented for the class instead.
- Any exceptions that a member function throws. You should document
any and all exceptions that a member function throws so that other
programmers know what their code will need to catch. The javadoc @exception
tag, discussed in (section 1.4.2 "A Quick Overview of javadoc"),
is used for this.
- Visibility decisions. If you feel that your choice of visibility
for a member function will be questioned by other developers, perhaps you
have made a member function public even though no other objects invoke the
member function yet, then you should document your decision. This will
help to make your thinking clear to other developers so that they do not
waste time worrying about why you did something questionable.
- How a member function changes the object. If a member function
changes an object, for example the withdraw() member function of a
bank account modifies the account balance then this needs to be indicated.
This information is needed so that other Java programmers know exactly how
a member function invocation will affect the target object.
- Avoid the use of headers containing information such as author,
phone numbers, dates of creation and modification, and location of unit
(or filename), because this information rapidly becomes obsolete. Place
ownership copyright notices at the end of the unit, For instance - readers
do not want to have to scroll through two or three pages of text that is
not useful for the understanding of the program, and/or text that does not
carry any program information at all, such as a copyright notice. Avoid
the use of vertical bars or closed frames or boxes, which just add visual
noise and are difficult to keep consistent. Use a configuration management
tool to keep unit history.
- Examples of how to invoke the member function if appropriate. One
of the easiest ways to determine how a piece of code works it to look at
an example. Consider including an example or two of how to invoke a member
function.
- Applicable pre-conditions
and
- Applicable preconditions and post-conditions.
A pre-condition is a constraint under which a member function will function
properly, and a post-condition is a property or assertion that will be true
after a member function is finished running [MEY88]. In
many ways pre-conditions and post-conditions describe the assumptions that
you have made when writing a member function [AMB98],
defining exactly the boundaries of how a member function is used.
- All concurrency issues. Concurrency is a new and complex concept for
many developers and at best it is an old and complex topic for experienced
concurrent programmers. The end result is that if you use the concurrent
programming features of Java then you need to document it thoroughly. [LEA97]
suggests that when a class includes both synchronized and unsynchronized
member functions you must document the execution context that a member
function relies on, especially when it requires unrestricted access so that
other developers can use your member functions safely. When a setter, a
member function that updates a field, of a class that implements the Runnable
interface is not synchronized then you should document your reason(s) why.
Finally, if you override or overload a member function and change its
synchronization you should also document why.
You should document something only when it adds to
the clarity of your code. You would not document all of the factors
described above for each and every member function because not all factors are
applicable to every member function. You would however document several of
them for each member function that you write.
Internal Documentation 
In addition to the member function documentation, you also
need to include comments within your member functions to describe your work.
The goal is to make your member function easier to understand, to maintain,
and to enhance.
There are two types of comments that you should use to document the
internals of your codeC-style comments ( /* & */) and single-line
comments ( // ). As discussed above, you should seriously consider choosing
one style of comments for documenting the business logic of your code and
one for commenting out unneeded code. It is suggested that you use
single-line comments for your business logic, because you can use this style
of comments both for full comment lines and for inline comments that follow
at the end of a line of code. Use C-style comments to document out lines of
unneeded code because it makes it easier to take out several lines with only
one comment. Furthermore, because C-style comments look so much like
documentation comments their use can be confusing, taking away from the
understandability of your code. Therefore use them sparingly.
Internally, you should always document:
- Control structures. Describe what each control structure, such as
comparison statements and loops. You should not have to read all the code
in a control structure to determine what it does, instead you should just
have to look at a one or two line comment immediately preceding it.
- Why, as well as what, the code does. You can always look at a
piece of code and figure out what it does, but for code that is not
obvious you can rarely determine why it is done that way. For example, you
can look at a line of code and easily determine that a 5% discount is
being applied to the total of an order. That is easy. What is not easy is
figuring out WHY that discount is being applied. Obviously there is some
sort of business rule that says to apply the discount, so that business
rule should at least be referred to in your code so that other developers
can understand why your code does what it does.
- Local variables. Although we will discuss this in greater detail
in chapter 4, each local variable defined in a member function should be
declared on its own line of code and should usually have an inline comment
describing its use.
- Difficult or complex code. If you find that you either can. t
rewrite it, or do not have the time, then you must document thoroughly any
complex code in a member function. A general rule of thumb is that if your
code is not obvious, then you need to document it.
- The processing order. If there are statements in your code that
must be executed in a defined order then you should ensure that this fact
gets documented [AMB98]. There. s nothing worse than
making a simple modification to a piece of code only to find that it no
longer works, then spending hours looking for the problem only to find
that you have gotten things out of order.
Document Your Closing Braces Every so often you
will find that you have control structures within control structures within
control structures. Although you should avoid writing code like this,
sometimes you find that it is better to write it this way. The problem is
that it becomes confusing which ending brace, the } character, belongs to
which control structure. The good news is that some code editors support a
feature that when you select a open brace it will automatically highlight
the corresponding closing one, the bad news is that not every editor
supports this. I have found that by marking the ending braces with an inline
comment such as //end if, //end for, //end switch,
& makes your code easier to understand.
This section covers several techniques that help to separate
the professional developers from the hack coders. These techniques are:
- Document your code
- Paragraph your code
- Use whitespace
- Follow the thirty-second rule
- Specify the order of message sends
- Write short, single command lines
Document Your Code
Remember, if your code is not worth documenting then it is not worth
keeping[NAG95]. When you apply the documentation
standards and guidelines proposed in this paper appropriately you can greatly
enhance the quality of your code.
Paragraph/Indent
Your Code
One way to improve the readability of a member function is
to paragraph it, or in other words indent your code within the scope of a code
block. Any code within braces, the { and } characters, forms a
block. The basic idea is that the code within a block should be uniformly
indented one unit.
The Java convention appears to be that the open brace is to be put on the
line following the owner of the block and that the closing brace should be
indented one level. The important thing as pointed out by [LAF97]
is that your organization chooses an indentation style and sticks to it. Use
the same indentation style that your Java development environment uses for the
code that it generates.
Use Whitespace in Your Code A
few blank lines, called whitespace, added to your Java code can help to make
it much more readable by breaking it up into small, easy-to-digest sections. [VIS96]
suggests using a single blank line to separate logical groups of code, such as
control structures, with two blank lines to separate member function
definitions. Without whitespace it is very difficult to read and to
understand.
Follow The
Thirty-Second Rule
Other programmers should be able to look at your member
function and be able to fully understand what it does, why it does it, and how
it does it in less than 30 seconds. If this is not possible then your code is
too difficult to maintain and should be improved. Thirty seconds, that. s it.
A good rule of thumb is that if a member function is more than a screen then
it is probably too long.
Write Short, Single Command Lines
Your code should do one thing per line. Back in the days of
punch cards it made sense to try to get as much functionality as possible on a
single line of code. Whenever you attempt to do more than one thing on a
single line of code you make it harder to understand. Why do this? We want to
make our code easier to understand so that it is easier to maintain and
enhance. Just like a member function should do one thing and one thing only,
you should only do one thing on a single line of code.
Furthermore, you should write code that remains visible on the screen [VIS96].
You should not have to scroll your editing window to the right to read the
entire line of code, including code that uses inline comments.
Specify the Order
of Operations
A really easy way to improve the understandability of your
code is to use parenthesis, also called "round brackets," to specify
the exact order of operations in your Java code [NAG95];
[AMB98]. If you have to know the order of operations for
a language to understand your source code then something is seriously wrong.
This is mostly an issue for logical comparisons where you AND and OR several
other comparisons together. Note that if you use short, single command lines
as suggested above then this really should not crop up as an issue.
The term field is here used to refer to a field, which the Beans
Development Kit (BDK) calls a property [DES97]. A field is
a piece of data that describes an object or class. Fields may be base data type
like a string or a float, or may be an object such as a customer or bank
account.
You should use a full English descriptor to name your fields
[GOS96]; [AMB98] to make it obvious
what the field represents. Fields that are collections, such as arrays or
vectors, should be given names that are plural to indicate that they represent
multiple values.
Examples:
firstName
zipCode
unitPrice
discountRate
orderItems
For names of components (interface widgets) you should use a
full English descriptor postfixed by the widget type. This makes it easy for
you to identify the purpose of the component as well as its type, making it
easier to find each component in a list (many visual programming environments
provide lists of all components in an applet or application and it can be
confusing when everything is named button1, button2, & ).
Examples:
okButton
customerList
fileMenu
newFileMenuItem
Alternative for Naming Components . Hungarian Notation
The "Hungarian Notation" [MCO93]
is based on the principle that a field should be named using the following
approach: xEeeeeeEeeeee where x indicates the component type and EeeeeEeeeee
is the full English descriptor.
Examples:
pbOk
lbCustomer
mFile
miNewFile
The main advantage is that this is an industry standard common for C++ code
so many people already follow it. Furthermore, developers can quickly judge
from the name of the variable its type and how it is used. The main
disadvantages are that the prefix notation becomes cumbersome when you have a
lot of the same type of widget and you break from the full English descriptor
naming convention.
Alternative for Naming Components . Postfix-Hungarian Notation
Basically a combination of the other two alternatives, it
results in names such as okPb, customerLb, fileM, and newFileMi.
The main advantage is that the name of the component indicates the widget type
and that widgets of the same type are not grouped together in an alphabetical
list. The main disadvantage is that you still are not using a full English
description, making the standard harder to remember because it deviates from
the norm.
Set Component Name Standards. Whatever convention you
choose, you will want to create a list of "official" widget names.
For example, when naming buttons do you use Button or PushButton,
b or pb? Create a list and make it available to every Java
developer in your organization
In Java, constants, values that do not change, are typically
implemented as static final fields of classes. The recognized
convention is to use full English words, all in uppercase, with underscores
between the words [GOS96].
Examples:
MINIMUM_BALANCE
MAX_VALUE
DEFAULT_START_DATE
The main advantage of this convention is that it helps to distinguish
constants from variables. We will see later in the document that you can
greatly increase the flexibility and maintainability of your code by not
defining constants, instead you should define getter member functions that
return the value of constants.
A collection, such as an array or a vector, should be given
a pluralized name representing the types of objects stored by the array. The
name should be a full English descriptor with the first letter of all
non-initial words capitalized.
Examples:
customers
orderItems
aliases
The main advantage of this convention is that it helps to distinguish
fields that represent multiple values (collections) from those that represent
single values (non-collections).
When fields are declared protected there is the
possibility of member functions in subclasses to directly access them,
effectively increasing the coupling within a class hierarchy. This makes your
classes more difficult to maintain and to enhance, therefore it should be
avoided. Fields should never be accessed directly, instead accessor member
functions (see below) should be used.
Visibility |
Description |
Proper Usage |
public |
A public field can be accessed
by any other member function in any other object or class. |
Do not make fields public. |
protected |
A protected field can be
accessed by any member function in the class in which it is declared or by
any member functions defined in subclasses of that class. |
Do not make fields protected. |
private |
A private field can only be
accessed by member functions in the class in which it is declared, but not
in the subclasses. |
All fields should be private
and be accessed by getter and setter member functions (accessors). |
For fields that are not persistent (they will not be saved to permanent
storage) you should mark them as either static or transient [DES97].
This makes them conform to the conventions of the BDK.
Do Not "Hide" Names
Name hiding refers to the practice of naming a local
variable, argument, or field the same (or similar) as that of another one of
greater scope. For example, if you have a field called firstName do not
create a local variable or parameter called firstName, or anything
close to it like firstNames or fistName. This makes your code
difficult to understand and prone to bugs because other developers, or you,
will misread your code while they are modifying it and make difficult to
detect errors.
Every field should be documented well enough so that other
developers can understand it. To be effective, you need to document:
- Its description. You need to describe a field so that people know
how to use it.
- Document all applicable invariants. Invariants of a field are the
conditions that are always true about it. For example, an invariant about
the field dayOfMonth might be that its value is between 1 and 31
(obviously you could get far more complex with this invariant, restricting
the value of the field based on the month and the year). By documenting the
restrictions on the value of a field you help to define important business
rules, making it easier to understand how your code works.
- Examples. For fields that have complex business rules associated
with them you should provide several example values so as to make them
easier to understand. An example is often like a picture: it is worth a
thousand words.
- Concurrency issues. Concurrency is a new and complex concept for
many developers, actually, at best it is an old and complex topic for
experienced concurrent programmers. The end result is that if you use the
concurrent programming features of Java then you need to document it
thoroughly.
- Visibility decisions. If you have declared a field to be anything
but private then you should document why you have done so. Field visibility
is discussed in (section 3.2 "Field Visibility") above, and the
use of accessor member functions to support encapsulation is covered in
(section 3.4 "The Use of Accessor Member Functions") below. The
bottom line is that you would better have a really good reason for not
declaring a variable as private.
In addition to naming conventions, the maintainability of
fields is achieved by the appropriate use of accessor member functions,
member functions that provide the functionality to either update a field or to
access its value. Accessor member functions come in two flavors: setters
(also called mutators) and getters. A setter modifies the value
of a variable, whereas a getter obtains it for you.
Although accessor member functions used to add overhead to your code, Java
compilers are now optimized for their use, this is no longer true. Accessors
help to hide the implementation details of your class. By having at most two
control points from which a variable is accessed, one setter and one getter,
you are able to increase the maintainability of your classes by minimizing the
points at which changes need to be made. Optimization of Java code is
discussed in (section 7.3 "Optimizing Java Code").
One of the most important standards that your
organization can enforce is the use of accessors. Some developers do
not want to use accessor member functions because they do not want to type the
few extra keystrokes required (for example, for a getter you need to type in .
get. and . (). above and beyond the name of the field). The bottom line is
that the increased maintainability and extensibility from using accessors more
than justifies their use.
Accessors Are The Only Place To Access Fields. A key
concept with the appropriate use of accessor member functions is that the ONLY
member functions that are allowed to directly work with a field are the
accessor member functions themselves. Yes, it is possible for to directly
access a private field within the member functions of the class in which the
field is defined but you do not want to do so because you would increase the
coupling within your class.
"Good program design seeks to isolate parts of a
program from unnecessary, unintended, or otherwise unwanted outside
influences. Access modifiers (accessors) provide an explicit and checkable
means for the language to control such contacts." [KAN97]
Accessor member functions improve the maintainability of your classes in
the following ways:
- Updating fields. You have single points of update for each field,
making it easier to modify and to test. In other words your fields are
encapsulated.
- Obtaining the values of fields. You have complete control over how
fields are accessed and by whom.
- Obtaining the values of constants and the names of classes. By
encapsulating the value of constants and of class names in getter member
functions when those values/names change you only need to update the value
in the getter and not every line of code where the constant/name is used.
- Initializing fields. The use of lazy initialization ensures that
fields are always initialized and that they are initialized only if they are
needed.
- Reduction of the coupling between a subclass and its superclass(es).
When subclasses access inherited fields only through their corresponding
accessor member functions, it makes it possible to change the implementation
of fields in the superclass without affecting any of its subclasses,
effectively reducing coupling between them. Accessors reduce the risk of the
"fragile base class" where changes in a superclass ripple
throughout its subclasses.
- Encapsulating changes to fields. If the business rules pertaining to
one or more fields change you can potentially modify your accessors to
provide the same ability as before the change, making it easier for you to
respond to the new business rules.
- Simplification of concurrency issues. [LEA97]
points out that setter member functions provide a single place to include a notifyAll
if you have waits based on the value of that field. This makes moving to a
concurrent solution much easier.
- Name hiding becomes less of an issue. Although you should avoid name
hiding, giving local variables the same names as fields, the use of
accessors to always access fields means that you can give local variables
any name you want. You do not have to worry about hiding field names because
you never access them directly anyway.
When You may not use accessors: The only
time that you might want to not use accessors is when execution time is of the
utmost importance, however, it is a very rare case indeed that the increased
coupling within your application justifies this action.
Getter member functions should be given the name . get. +
field name, unless the field represents a boolean (true or false) and then the
getter is given the name . is. + field name. Setter member functions should be
given the name . set. + field name, regardless of the field type [GOS96];
[DES97]. Note that the field name is always in mixed case
with the first letter of all words capitalized. This naming convention is used
consistently within the JDK and is what is required for beans development.
Examples:
Field |
Type |
Getter
name |
Setter
name |
firstName
|
string
|
getFirstName()
|
setFirstName()
|
address
|
Address
object
|
getAddress()
|
setAddress()
|
persistent
|
boolean
|
isPersistent()
|
setPersistent()
|
customerNo
|
int
|
getCustomerNo()
|
setCustomerNo()
|
orderItems
|
Array of
OrderItem
objects
|
getOrderItems()
|
setOrderItems()
|
Advanced Techniques for Accessors
Accessors can be used for more than just getting and setting
the values of instance fields. This section discusses how to increase the
flexibility of your code by using accessors to:
- Initialize the values of fields
- Access constant values
- Access collections
- Access several fields simultaneously
Lazy Initialization
Variables need to be initialized before they are accessed.
There are two lines of thought to initialization: Initialize all variables at
the time the object is created (the traditional approach) or initialize at the
time of first use. The first approach uses special member functions that are
invoked when the object is first created, called constructors. Although this
works, it often proves to be error prone. When adding a new variable you can
easily forget to update the constructors (An alternative approach is called lazy
initialization where fields are initialized by their getter member
functions, as shown below (Note how a setter member function is used within
the getter member function). Notice the member function checks to see if the
branch number is zero, if it is, then it sets it to the appropriate default
value.
/** Answers the branch number, which is the leftmost
four digits of the full account number.
Account numbers are in the format BBBBAAAAAA.
*/
protected int getBranchNumber()
{
if( branchNumber == 0)
{
// The default branch number is 1000, which
// is the main branch in downtown Bedrock.
setBranchNumber(1000);
}
return branchNumber;
}
It is quite common to use lazy initialization for fields that are actually
other objects stored in the database. For example, when you create a new
inventory item you do not need to fetch whatever inventory item type from the
database that you have set as a default. Instead, use lazy initialization to
set this value the first time it is accessed so that you only have to read the
inventory item type object from the database when and if you need it. This
approach is advantageous for objects that have fields that are not regularly
accessed. Why incur the overhead of retrieving something from persistent
storage if you are not going to use it?
Whenever lazy initialization is used in a getter member function you should
document why the default value is what it is, as we saw in the example above.
When you do this you take the mystery out of how fields are used in your code,
improving both its maintainability and extensibility.
The common Java idiom is to implement constant values as
static final fields. This approach makes sense for "constants" that
are guaranteed to be stable. For example the class Boolean implements
two static final fields called TRUE and FALSE which
represents the two instances of that class. It would also make sense for a DAYS_IN_A_WEEK
constant whose value probably is never going to change.
However, many so-called business "constants" change over time
because the business rule changes. Consider the following example: The Archon
Bank of Cardassia (ABC) has always insisted that an account has a minimum
balance of $500 if it is to earn interest. To implement this, we could add a
static field named MINIMUM_BALANCE to the class Account that would be
used in the member functions that calculate interest. Although this would
work, it is not flexible. What happens if the business rules change and
different kinds of accounts have different minimum balances, perhaps $500 for
savings accounts but only $200 for checking accounts? What would happen if the
business rule were to change to a $500 minimum balance in the first year, $400
in the second, $300 in the third, and so on? Perhaps the rule will be changed
to $500 in the summer but only $250 in the winter? Perhaps a combination of
all of these rules will need to be implemented in the future.
The point to be made is that implementing constants as fields is not
flexible, a much better solution is to implement constants as getter member
functions. In our example above, a static (class) member function called getMinimumBalance()
is far more flexible than a static field called MINIMUM_BALANCE because
we can implement the various business rules in this member function and
subclass it appropriately for various kinds of accounts.
/** Get the value of the account number. Account numbers are in the following
format: BBBBAAAAAA, where BBBB is the branch number and
AAAAAA is the branch account number.
*/
public long getAccountNumber()
{
return ( ( getBranchNumber() * 100000 ) + getBranchAccountNumber() );
}
/**
Set the account number. Account numbers are in the following
format: BBBBAAAAAA where BBBB is the branch number and
AAAAAA is the branch account number.
*/
public void setAccountNumber(int newNumber)
{
setBranchAccountNumber( newNumber % 1000000 );
setBranchNumber( newNumber / 1000000 );
}
Another advantage of constant getters is that they help to increase
consistency of your code. Consider the code shown above . it does not work
properly. An account number is the concatenation of the branch number and the
branch account number. Testing our code, we find that the setter member
function, setAccountNumber() does not update branch account numbers
properly (it takes the three leftmost digits, not four). That is because we
used 1,000,000 instead of 100,000 to extract the field branchAccountNumber.
Had we used a single source for this value, the constant getter getAccountNumberDivisor()
as we see in below, our code would have been more consistent and would have
worked.
/**
Returns the divisor needed to separate the branch account number from the
branch number within the full account number.
Full account numbers are in the format BBBBAAAAAA.
*/
public int getAccountNumberDivisor()
{
return ( (long) 1000000);
}
/**
Get the value of the account number. Account numbers are in the following
format: BBBBAAAAAA, where BBBB is the branch number and
AAAAAA is the branch account number.
*/
public long getAccountNumber()
{
return ( ( getBranchNumber() * getAccountNumberDivisor() ) +
getBranchAccountNumber() );
}
/**
Set the account number. Account numbers are in the following
format: BBBBAAAAAA where BBBB is the branch number and
AAAAAA is the branch account number.
*/
public void setAccountNumber(int newNumber)
{
setBranchAccountNumber( newNumber % getAccountNumberDivisor() );
setBranchNumber( newNumber / getAccountNumberDivisor() );
}
By using accessors for constants we decrease the chance of bugs and at the
same time increase the maintainability of our system. When the layout of an
account number changes, and we know that it eventually will, chances are that
our code will be easier to change because we have both hidden and centralized
the information needed to build/break up account numbers.
The main purpose of accessors is to encapsulate the access
to fields so as to reduce the coupling within your code. Collections, such as
arrays and vectors, being more complex than single value fields naturally need
to have more than just the standard getter and setter member function
implemented for them. In particular, because you can add and remove to and
from collections, accessor member functions need to be included to do so. Add
the following accessor member functions where appropriate for a field that is
a collection:
Member
Function type |
Naming
convention |
Example |
Getter for the
collection |
getCollection()
|
getOrderItems()
|
Setter for the
collection |
setCollection()
|
setOrderItems()
|
Insert an object
into the collection |
insertObject()
|
insertOrderItem()
|
Delete an object
from the collection |
deleteObject()
|
deleteOrderItem()
|
Create and add a
new object into the collection |
newObject()
|
newOrderItem()
|
The advantage of this approach is that the collection is fully
encapsulated, allowing you to later replace it with another structure, perhaps
a linked list or a B-tree.
One of the strengths of accessor member functions is that
they enable you to enforce business rules effectively. Consider for example a
class hierarchy of shapes. Each subclass of Shape knows its position
via the use of two fields . xPosition and yPosition . and can be
moved on the screen on a two-dimensional plane via invoking the member
function move(Float xMovement, Float yMovement). For our purposes it
does not make sense to move a shape along one axis at a time, instead we will
move along both the x and the y axis simultaneously (it is acceptable to pass
a value of 0.0 as for either parameter of the move() member function).
The implication is that the move() member function should be public,
but the member functions setXPosition() and setYPosition()
should both be private, being invoked by the move() member function
appropriately.
An alternative implementation would be to introduce a setter member
function that updates both fields at once, as shown below. The member
functions setXPosition() and setYPosition() would still be
private so that they may not be invoked directly by external classes or
subclasses (you would want to add some documentation, shown below, indicating
that they should not be directly invoked).
/** Set the position of the shape */
protected void setPosition(Float x, Float y)
{
setXPosition(x);
setYPosition(y);
}
/** Set the x position . Important: Invoke setPosition(), not this member function. */
private void setXPosition(Float x)
{
xPosition = x;
}
/** Set the y position of the shape
Important: Invoke setPosition(), not this member function.
*/
private void setYPosition(Float y)
{
yPosition = y;
}
Always strive to make them protected, so that only
subclasses can access the fields. Only when an . outside class. needs to
access a field should you make the corresponding getter or setter public. Note
that it is common that the getter member function be public and the setter
protected.
Sometimes you need to make setters private to ensure certain invariants
hold. For example, an Order class may have a field representing a
collection of OrderItem instances, and a second field called orderTotal
which is the total of the entire order. The orderTotal is a convenience
field that is the sum or all sub-totals of the ordered items. The only member
functions that should update the value of orderTotal are those that
manipulate the collection of order items. Assuming that those member functions
are all implemented in Order, you should make setOrderTotal()
private, even though getOrderTotal() is more than likely public.
Always Initialize Static Fields 
Static fields, also known as class fields, should be given
valid values because you cannot assume that instances of a class will be
created before a static field is accessed.
A local variable is an object or data item that is defined
within the scope of a block, often a member function. The scope of a local
variable is the block in which it is defined. The important coding standards for
local variables focus on:
- Naming conventions
- Documentation conventions
- Declarations
In general, local variables are named following the same
conventions as used for fields, in other words use full English descriptors
with the first letter of any non-initial word in uppercase.
For the sake of convenience, however, this naming convention is relaxed for
several specific types of local variable:
- Streams
- Loop counters
- Exceptions
When there is a single input and/or output stream being
opened, used, and then closed within a member function the common convention
is to use in and out for the names of these streams,
respectively [GOS96]. For a stream used for both input
and output, the implication is to use the name inOut.
A common alternative to this naming convention, although conflicting with
Sun's recommendations, is to use the names inputStream, outputStream,
and ioStream instead of in, out, and inOut
respectively.
Because loop counters are a very common use for local
variables, and because it was acceptable in C/C++, in Java programming the use
of i, j, or k, is acceptable for loop counters [GOS96].
If you use these names for loop counters, use them consistently.
A common alternative is to use names like loopCounter or simply
counter, but the problem with this approach is that you often find names like counter1
and counter2 in member functions that require more than one counter.
The bottom line is that i, j, k work as counters, they.
re quick to type in, and they. re generally accepted.
Because exception handling is also very common in Java
coding the use of the letter e for a generic exception is considered
acceptable [GOS96].
There are several conventions regarding the declaration and
documentation of local variable in Java. These conventions are:
- Declare one local variable per line of code. This is consistent with
one statement per line of code and makes it possible to document each
variable with an inline comment.
- Document local variables with an inline comment. Inline commenting
is a style in which a single line comment, denoted by //, immediately
follows a command on the same line of code (this is called an endline
comment). You should document what a local variable is used for and where
appropriate why it is used, making your code easier to understand.
- Use local variables for one thing only. Whenever you use a local
variable for more than one reason you effectively decrease its cohesion,
making it difficult to understand. You also increase the chances of
introducing bugs into your code from the unexpected side effects of previous
values of a localvariable from earlier in the code. Yes, reusing local
variables is more efficient because less memory needs to be allocated, but
reusing local variables decreases the maintainability of your code and makes
it more fragile. This usually is not worth the small savings from not having
to allocate more memory.
General Comments About Declaration
Local variables that are declared between lines of code, for
example within the scope of an if statement, can be difficult to find by
people not familiar with your code.
One alternative to declaring local variables immediately before their first
use is to instead declare them at the top of the code. Because your member
functions should be short anyway, see (section 2.4.5 "Write Short, Single
Command Lines"), it should not be all that bad having to go to the top of
your code to determine what the local variable is all about.
The standards that are important for parameters/arguments to member functions
focus on how they are named and how they are documented. The term parameter
is used to refer to a member function argument.
Parameters should be named following the exact same
conventions as for local variables. As with local variables, name hiding is an
issue.
Examples:
customer
inventoryItem
photonTorpedo
in
e
A viable alternative, taken from Smalltalk, is to use the naming conventions
for local variables, with the addition of "a" or "an" on the
front of the name. The addition of "a" or "an" helps to make
the parameter stand out from local variables and fields, and avoids the name
hiding problem. This is the preferred approach.
Examples:
aCustomer
anInventoryItem
aPhotonTorpedo
anInputStream
anException
Parameters to a member function are documented in the header
documentation for the member function using the javadoc @param
tag. You should describe:
- What it should be used for. You need to document what a parameter is
used for so that other developers understand the full context of how the
parameter is used.
- Any restrictions or pre-conditions.
If the full range of values for a parameter is not acceptable
to a member function, then the invoker of that member function needs to know.
Perhaps a member function only accepts positive numbers, or strings of less than
five characters.
- Examples. If it is not completely obvious what a parameter should be,
then you should provide one or more examples in the documentation.
Use Interfaces for Parameter Types. Instead
of specifying a class, such as Object, for the type of a parameter, if
appropriate specify an interface, such as Runnable, if appropriate. The
advantage is that this approach, depending on the situation, can be more
specific (Runnable is more specific than Object), or may potentially be a better
way to support polymorphism (instead of insisting on a parameter being an
instance of a class in a specific class hierarchy, you specify that it supports
a specific interface implying that it only needs to be polymorphically compliant
to what you need)
This chapter concentrates on standards and guidelines for classes,
interfaces, packages, and compilation units. A class is a template from which
objects are instantiated (created). Classes contain the declaration of fields
and member functions. Interfaces are the definition of a common signature,
including both member functions and fields, which a class that implements an
interface must support. A package is a collection of related classes. Finally, a
compilation unit is a source code file in which classes and interfaces are
declared. Because Java allows compilation units to be stored in a database an
individual compilation unit may not directly relate to a physical source code
file.
The standards that are important for classes are based on:
- Naming conventions
- Documentation conventions
- Declaration conventions
- The public and protected interface
The standard Java convention is to use a full English
descriptor starting with the first letter capitalized using mixed case for the
rest of the name[GOS96]; [AMB98].
Class names shall be in singular form.
Examples:
Customer
Employee
Order
OrderItem
FileStream
String
The following information should appear in the documentation
comments immediately preceding the definition of a class:
- The purpose of the class. Developers need to know the general
purpose of a class so they can determine whether or not it meets their
needs. Make it a habit to document any good things to know about a class,
for example is it part of a pattern or are there any interesting limitations
to using it [AMB98].
- Known bugs. If there are any outstanding problems with a class they
should be documented so that other developers understand the
weaknesses/difficulties with the class. Furthermore, the reason for not
fixing the bug should also be documented. Note that if a bug is specific to
a single member function then it should be directly associated with the
member function instead.
- The development/maintenance history of the class. It is common
practice to include a history table listing dates, authors, and summaries of
changes made to a class. The purpose of this is to provide maintenance
programmers insight into the modifications made to a class in the past, as
well as to document who has done what to a class.
- Document applicable invariants. An invariant is a set of assertions
about an instance or class that must be true at all "stable"
times, where a stable time is defined as the period before a member function
is invoked on the object/class and immediately after a member function is
invoked [MEY88]. By documenting the invariants of a
class you provide valuable insight to other developers as to how a class can
be used.
- The concurrency strategy. Any class that implements the interface Runnable
should have its concurrency strategy fully described. Concurrent programming
is a complex topic that is new for many programmers, therefore you need to
invest the extra time to ensure that people can understand your work. It is
important to document your concurrency strategy and why you chose that
strategy over others. Common concurrency strategies [LEA97]
include the following: Synchronized objects, balking objects, guarded
objects, versioned objects, concurrency policy controllers, and acceptors.
One way to make your classes easier to understand is to
declare them in a consistent manner. The common approach in Java is to declare
a class in the following order:
public member functions
public fields
protected member functions
protected fields
private member functions
private fields
[LAF97] points out that constructors and finalize()
should be listed first, presumably because these are the first member
functions that another developer will look at first to understand how to use
the class. Furthermore, because we have a standard to declare all fields as
private, the declaration order really boils down to:
constructors
finalize()
public member functions
protected member functions
private member functions
private fields
Within each grouping of member functions it is common to list them in
alphabetical order. Many developers choose to list the static member functions
within each grouping first, followed by instance member functions, and then
within each of these two sub-groupings list the member functions
alphabetically. Both of these approaches are valid, you just need to choose
one and stick to it.
One of the fundamentals of object-oriented design is to
minimize the public interface of a class. There are several reasons for this:
- Learnability. To learn how to use a class you should only have to
understand its public interface. The smaller the public interface, the
easier a class is to learn.
- Reduced coupling. Whenever the instance of one class sends a message
to an instance of another class, or directly to the class itself, the two
classes become coupled. Minimizing the public interface implies that you are
minimizing the opportunities for coupling.
- Greater flexibility. This is directly related to coupling. Whenever
you want to change the way that a member function in your public interface
is implemented, perhaps you want to modify what the member function returns,
then you potentially have to modify any code that invokes the member
function. The smaller the public interface the greater the encapsulation and
therefore the greater your flexibility.
It is clear that it is worth your while to minimize the public interface,
but often what is not so clear is that you also want to minimize the protected
interface as well. The basic idea is that from the point of view of a
subclass, the protected interfaces of all of its superclasses are effectively
public. Any member function in the protected interface can be invoked by a
subclass. Therefore, you want to minimize the protected interface of a class
for the same reasons that you want to minimize the public interface.
Define The Public Interface First. Most experienced
developers define the public interface of a class before they begin coding it.
First, if you do not know what services/behaviors a class will perform, then
you still have some design work to do. Second, it enables them to stub out the
class quickly so that other developers who rely on it can at least work with
the stub until the "real" class has been developed. Third, this
approach provides you with an initial framework around which to build your
class.
The standards that are important for interfaces are based
on:
- Naming conventions
- Documentation conventions
The Java convention is to name interfaces using mixed case
with the first letter of each word capitalized. The preferred Java convention
for the name of an interface is to use a descriptive adjective, such as Runnable
or Cloneable, although descriptive nouns, such as Singleton or DataInput,
are also common [GOS96].
Alternative:
Prefix the letter . I. to the interface name. [COA97]
suggest appending the letter . I. to the front of an interface names,
resulting in names like ISingleton or IRunnable. This approach
helps to distinguish interface names from class and package names. I like
this potential naming convention for the simple fact that it makes your
class diagrams, sometimes referred to as object models, easier to read. The
main disadvantage is that the existing interfaces, such as Runnable,
are not named using this approach. This interface naming convention is also
popular for Microsoft. s COM/DCOM architecture.
The following information should appear in the documentation
comments immediately preceding the definition of an interface:
- The purpose. Before other developers will use an interface, they
need to understand the concept that it encapsulates. In other words, they
need to know its purpose. A really good test of whether or not you need to
define an interface is whether or not you can easily describe its purpose.
If you have difficulties describing it, then chances are pretty good you do
not need the interface to begin with. Because the concept of interfaces is
new to Java, people are not yet experienced in their appropriate use and
they are likely to overuse them because they are new.
- How it should and should not be used. Developers need to know both
how an interface is to be used, as well as how it should not be used [COA97].
Because the signature for member functions is defined in an interface, for
each member function signature you should follow the member function
documentation conventions discussed in chapter 2.
The standards that are important for packages are based on:
- Naming conventions
- Documentation conventions
There are several rules associated with the naming of
packages. In order, these rules are:
- Identifiers are separated by periods. To make package names more
readable, Sun suggests that the identifiers in package names be separated by
periods. For example, the package name java.awt is comprised of two
identifiers, java and awt.
- The standard java distribution packages from Sun begin with the
identifier . java. . Sun has reserved this right so that the standard
java packages are named in a consistent manner regardless of the vendor of
your Java development environment.
- Local package names begin with an identifier that is not all upper case.
Local packages are ones that are used internally within your organization
and that will not be distributed to other organizations. Examples of these
package names include persistence.mapping.relational and
interface.screens.
- Global package names begin with the reversed Internet domain name for
your organization. A package that is to be distributed to multiple
organizations should include the name of the originating organization. s
domain name, with the top-level domain type capitalized. For example, to
distribute the previous packages, they would be named com.rational.www.persistence.mapping.relational
and com.rational.www.interface.screens.0
You should maintain one or more external documents that
describe the purpose of the packages developed by your organization. For each
package you should document:
- The rationale for the package. Other developers need to know what a
package is all about so that they can determine whether or not they want to
use it, and if it is a shared package whether or not they want to enhance or
extend it.
- The classes in the package. Include a list of the classes and
interfaces in the package with a brief, one-line description of each so that
other developers know what the package contains.
Tip: Create an HTML file, using the name of the package, and put it in the
appropriate directory for the package. The file shall be postfixed with .html.
The standards and guidelines for compilation units are based
on:
- Naming conventions
- Documentation conventions
A compilation unit, in this case a source code file, should
be given the name of the primary class or interface that is declared within
it. Use the same name for the package/class for the file name, using the same
case. The extension .java should be postfixed to the file name.
Examples:
Customer.java
Singleton.java
SavingsAccount.java
Although you should strive to have only one class or
interface declaration per file, it sometimes makes sense to define several
classes (or interfaces) in the same file. A general rule of thumb is that if
the sole purpose of class B is to encapsulate functionality that is needed
only by class A then it makes sense that class B appear in the same source
code file as class A. As a result, the following documentation conventions
apply to a source code file, and not specifically to a class:
- For files with several classes, list each class. If a file contains
more than one class you should provide a list of the classes and a brief
description for each.
- The file name and/or identifying information. The name of the file
should be included at the top of it. The advantage is that if the code is
printed you know what the source file for the code is.
- Copyright information. If applicable you should indicate any
copyright information for the file. It is common to indicate the year of the
copyright and the name of the individual/organization that holds the
copyright. Note that the code author may not be the holder of the copyright.
The general philosophy is to use exceptions only for errors: logic and
programming errors, configuration errors, corrupted data, resource exhaustion,
etc. The general rule is that the systems in normal condition and in the
absence of overload or hardware failure should not raise any exceptions.
Use exceptions to handle logic and programming errors,
configuration errors, corrupted data, resource exhaustion. Report
exceptions by the appropriate logging mechanism as early as possible,
including at the point of raise.
Minimize the number of exceptions exported from a given
abstraction.
In large systems, having to handle a large number of exceptions at each
level makes the code difficult to read and to maintain. Sometimes the
exception processing dwarfs the normal processing.
There are several ways to minimize the number of exceptions:
- Export only a few exceptions but provide "diagnosis"
primitives that allow querying the faulty abstraction or the bad object
for more detailed information about the nature of the problem that
occurred.
- Add "exceptional" states to the objects, and provide
primitives to check explicitly the validity of the objects.
Do not use exceptions for frequent, anticipated events.
There are several inconveniences in using exceptions to represent
conditions that are not clearly errors:
- It is confusing.
- It usually forces some disruption in the flow of control that is more
difficult to understand and to maintain.
- It makes the code more painful to debug, since most source-level
debuggers flag all exceptions by default.
For instance, do not use an exception as some form of extra value
returned by a function (like Value_Not_Found in a search); use a procedure
with an "out" parameter, or introduce a special value meaning
Not_Found, or pack the returned type in a record with a discriminant
Not_Found.
Do not use exceptions to implement control structures.
This is a special case of the previous rule: exceptions should not be
used as a form of "goto" statement.
Make sure status codes have an appropriate value.
When using status code returned by subprograms as an "out"
parameter, always make sure a value is assigned to the "out"
parameter by making this the first executable statement in the subprogram
body. Systematically make all statuses a success by default or a failure by
default. Think of all possible exits from the subprogram, including
exception handlers.
Perform safety checks locally; do not expect your client to do so.
That is, if a subprogram might produce erroneous output unless given
proper input, install code in the subprogram to detect and report invalid
input in a controlled manner. Do not rely on a comment that tells the client
to pass proper values. It is virtually guaranteed that sooner or later that
comment will be ignored, resulting in hard-to-debug errors if the invalid
parameters are not detected.
This chapter describes several standards/guidelines that are
important, but that are general enough that they need their own chapter.
Any Java class library or package that you purchase/reuse
from an external source should be certified as 100% pure Java [SUN97].
By enforcing this standard you are guaranteed that what you are reusing will
work on all platforms that you choose to deploy it on. You can obtain Java
classes, packages, or applets from a variety of sources, either a third-party
development company that specializes in Java libraries or another division or
project team within your organization.
The import statement allows the use of wildcards when
indicating the names of classes. For example, the statement
import java.awt.*;
brings in all of the classes in the package java.awt at once.
Actually, that. s not completely true. What really happens is that every class
that you use from the java.awt package will be brought into your code
when it is compiled, classes that you do not use will not be. Although this
sounds like a good feature, it reduces the readability of your code. A better
approach is to fully qualify the name of the classes that your code uses [LAF97];
[VIS96]. A better way to import classes is shown in the
example below:
import java.awt.Color;
import java.awt.Button;
import java.awt.Container;
Optimizing your code is one of the last things that
programmers should be thinking about, not one of the first. You leave
optimization to the end because you want to optimize only the code that needs
it. Very often a small percentage of your code results in the vast majority of
the processing time, and this is the code that you should be optimizing. A
classic mistake made by inexperienced programmers is to try to optimize all of
their code, even code that already runs fast enough
Do not waste your time optimizing code that nobody
cares about!
What should you look for when optimizing code? [KOE97]
points out that the most important factors are fixed overhead and
performance on large inputs. The reason for this is simple: fixed overhead
dominates the runtime speed for small inputs and the algorithm dominates for
large inputs. His rule of thumb is that a program that works well for both
small and large inputs will likely work well for medium-sized inputs.
Developers who have to write software that work on several hardware
platforms and/or operating systems need to be aware of idiosyncrasies in the
various platforms. Operations that might appear to take a particular amount
of time, such as the way that memory and buffers are handled, often show
substantial variations between platforms. It is common to find that you need
to optimize your code differently depending on the platform.
Another issue to be aware of when optimizing code is the
priorities of your users because depending on the context people will be
sensitive to particular delays. For example, your users will likely be
happier with a screen that draws itself immediately and then takes eight
seconds to load data than with a screen that draws itself after taking five
seconds to load data. In other words most users are willing to wait a little
longer as long as they. re given immediate feedback, important knowledge to
have when optimizing your code.
You do not always need to make your code run faster
to optimize it in the eyes of your users.
Although optimization may mean the difference between the
success and failure of your application, never forget that it is far more
important to get your code to work properly. Never forget that slow software
that works is always preferable to fast software that does not.
Object-oriented testing is a critical topic that has been
all but ignored by the object development community. The reality is that
either you or someone else will have to test the software that you write,
regardless of the language that you have chosen to work in. A test harness is
the collection of member functions, some embedded in the classes themselves
(this is called built-in tests) and some in specialized testing classes, that
is used to test your application.
- Prefix all testing member function names with . test. . This allows
you to quickly find all the testing member functions in your code. The
advantage of prefixing the name of test member functions with . test. is
that it allows you to easily strip your testing member functions out of your
source code before compiling the production version of it.
- Name all member function test member functions consistently. Method
testing is the act of verifying that a single member function performs as
defined. All member function test member functions should be named following
the format . testMemberFunctionNameForTestName. . For example, the
test harness member functions to test withdrawFunds() would include testWithdrawFundsForInsufficientFunds()
and testWithdrawFundsForSmallWithdrawal(). If you have a series of
tests for withdrawFunds() you may choose to write a member function
called testWithdrawFunds() that invokes all of them.
- Name all class test member functions consistently. Class testing is
the act of verifying that a single class performs as defined. All class test
member functions should be named following the format . testSelfForTestName.
. For example, the test harness member functions to test the Account class testSelfForSimultaneousAccess()
and testSelfForReporting().
- Create a single point for invoking the tests for a class. Develop a
static member function called testSelf() that invokes all class
testing and method testing member functions.
Document your test harness member functions. Document
your test harness member functions. The documentation should include a
description of the test as well as the expected results of the test.
Having a standards document in your possession does not automatically
make you more productive as a developer. To be successful you must choose to
become more productive, and that means you must apply these standards
effectively.
Using These Standards Effectively 
The following words of advice will help you to use the Java coding
standards and guidelines described in this white paper more effectively:
- Understand the standards. Take the time to understand why each
standard and guideline leads to greater productivity. For example, do not
declare each local variable on its own line just because these guidelines
told you to, do it because you understand that it increases the
understandability of your code.
- Believe in them. Understanding each standard is a start, but you
also need to believe in them too. Following standards should not be
something that you do when you have the time, it should be something that
you always do because you believe that this is the best way to code.
- Follow them while you are coding, not as an afterthought.
Documented code is easier to understand while you are writing it as well
as after it is written. Consistently named member functions and fields are
easier to work with during development as well as during maintenance.
Clean code is easier to work with during development and during
maintenance. The bottom line is that following standards will increase
your productivity while you are developing as well as make your code
easier to maintain (hence making maintenance developers more productive
too). If you write clean code right from the beginning you can benefit
from it while you are creating it.
- Make them part of your quality assurance process. Part of a code
inspection should be to ensure that source code follows the standards
adopted by your organization. Use standards as the basis from which you
train and mentor your developers to become more effective.
Other Factors That Lead to Successful Code 
- Program for people, not the machine. The primary goal of your
development efforts should be that your code is easy for other people to
understand. If no one else can figure it out, then it isn. t any good. Use
naming conventions. Document your code. Paragraph it.
- Design first, then code. Have you ever been in a situation where
some of the code that your program relies on needs to be changed? Perhaps
a new parameter needs to be passed to a member function, or perhaps a
class needs to be broken up into several classes. How much extra work did
you have to do to make sure that your code works with the reconfigured
version of the modified code? How happy were you? Did you ask yourself why
somebody didn. t stop and think about it first when he or she originally
wrote the code so that this didn. t need to happen? That they should have DESIGNED
it first? Of course you did. If you take the time to figure out how you
are going to write your code before you actually start coding you will
probably spend less time writing it. Furthermore, you will potentially
reduce the impact of future changes on your code simply by thinking about
them up front.
- Develop in small steps. Developing in small steps, writing a few
member functions, testing them, and then writing a few more member
functions is often far more effective than writing a whole bunch of code
all at once and then trying to fix it. It is much easier to test and fix
ten lines of code than 100, in fact, it is safe to say that you could
program, test, and fix 100 lines of code in ten 10-line increments in less
than half the time than you could write a single one-hundred line block of
code that did the same work. The reason for this is simple. Whenever you
are testing your code and you find a bug you almost always find the bug in
the new code that you just wrote, assuming of course that the rest of the
code was pretty solid to begin with. You can hunt down a bug a lot faster
in a small section of code than in a big one. By developing in small
incremental steps you reduce the average time that it takes to find a bug,
which in turn reduces your overall development time.
- Keep your code simple. Complex code might be intellectually
satisfying to write but if other people can. t understand it then it isn.
t any good. The first time that someone, perhaps even you, is asked to
modify a piece of complex code to either fix a bug or to enhance it
chances are pretty good that the code will get rewritten. In fact, you. ve
probably even had to rewrite somebody else. s code because it was too hard
to understand. What did you think of the original developer when you
rewrote their code, did you think that person was a genius or a jerk?
Writing code that needs to be rewritten later is nothing to be proud of,
so follow the KISS rule: Keep it simple, stupid.
- Learn common patterns, antipatterns, and idioms. There is a
wealth of analysis, design, and process patterns and antipatterns, as
well as programming idioms, available to guide you in increasing your
development productivity. See [AMB98]
and [AMB99] for more
information.
The primary goal of your development efforts should be that your code is
easy for other people to understand. If no one else can figure it out, then
it is not any good. Use naming conventions. Document your code. Paragraph
it.
- Design first, then code. Have you ever been in a situation where
some of the code that your program relies on needs to be changed? Perhaps
a new parameter needs to be passed to a member function, or perhaps a
class needs to be broken up into several classes. How much extra work did
you have to do to make sure that your code works with the reconfigured
version of the modified code? How happy were you? Did you ask yourself why
somebody did not stop and think about it first when he or she originally
wrote the code so that this did not need to happen? That they should have DESIGNED
it first? Of course you did. If you take the time to figure out how you
are going to write your code before you actually start coding you will
probably spend less time writing it. Furthermore, you will potentially
reduce the impact of future changes on your code simply by thinking about
them up front.
- Develop in small steps. Developing in small steps, writing a few
member functions, testing them, and then writing a few more member functions
is often far more effective than writing a whole bunch of code all at once
and then trying to fix it. It is much easier to test and fix ten lines of
code than 100, in fact, it is safe to say that you could program, test, and
fix 100 lines of code in ten 10-line increments in less than half the time
than you could write a single one-hundred line block of code that did the
same work. The reason for this is simple. Whenever you are testing your code
and you find a bug you almost always find the bug in the new code that you
just wrote, assuming of course that the rest of the code was pretty solid to
begin with. You can hunt down a bug a lot faster in a small section of code
than in a big one. By developing in small incremental steps you reduce the
average time that it takes to find a bug, which in turn reduces your overall
development time.
- Keep your code simple. Complex code might be intellectually
satisfying to write but if other people cannot understand it then it is not
any good. The first time that someone, perhaps even you, is asked to modify
a piece of complex code to either fix a bug or to enhance it chances are
pretty good that the code will get rewritten. In fact, you have probably
even had to rewrite somebody else. s code because it was too hard to
understand. What did you think of the original developer when you rewrote
their code, did you think that person was a genius or a jerk? Writing code
that needs to be rewritten later is nothing to be proud of, so follow the
KISS rule: Keep it simple, stupid.
- Learn common patterns, antipatterns, and idioms. There is a
wealth of analysis, design, and process patterns and antipatterns, as well
as programming idioms, available to guide you in increasing your
development productivity. See [AMB98]
and [AMB99] for more
information.
This chapter summarizes the guidelines given herein for your convenience.
This chapter is organized into several one-page summaries of our Java
coding standards, collected by topic. These topics are:
- Java naming conventions
- Java documentation conventions
- Java coding conventions
Before we summarize the rest of the standards and guidelines described in
this white paper, I would like to reiterate the prime directive:
When you go against a standard, document it. All standards, except
for this one, can be broken. If you do so, you must document why you broke
the standard, the potential implications of breaking the standard, and any
conditions that may/must occur before the standard can be applied to this
situation.
With a few exceptions discussed below, you should always use full English
descriptors when naming things. Furthermore, you should use lower case
letters in general, but capitalize the first letter of class names and
interface names, as well as the first letter of any non-initial word.
General Concepts:
- Use full English descriptors
- Use terminology applicable to the domain
- Use mixed case to make names readable
- Use short forms sparingly, but if you do so then use them
intelligently
- Avoid long names (less than 15 characters is a good idea)
- Avoid names that are similar or differ only in case
- Avoid underscores
Item |
Naming Convention |
Example |
Arguments/
parameters |
Use a full English
description of value/object being passed, possibly prefixing the name
with . a. or . an.. The important thing is to choose one approach and
stick to it. |
customer, account,
aCustomer, anAccount
|
Fields/
fields/
properties |
Use a full English
description of the field, with the first letter in lower case and the
first letter of any non-initial word in uppercase. |
firstName, lastName, warpSpeed
|
Boolean getter member
functions |
All boolean getters must be
prefixed with the word . is.. If you follow the naming standard for
boolean fields described above then you simply give it the name of the
field. |
isPersistent(), isString(),
isCharacter()
|
Classes |
Use a full English
description, with the first letters of all words capitalized. |
Customer, SavingsAccount
|
Compilation unit files |
Use the name of the class or
interface, or if there is more than one class in the file than the
primary class, prefixed with . .java. to indicate it is a source code
file. |
Customer.java,
SavingsAccount.java,
Singleton.java
|
Components/
widgets |
Use a full English
description which describes what the component is used for with the type
of the component concatenated onto the end. |
okButton, customerList,
fileMenu
|
Constructors |
Use the name of the class. |
Customer(), SavingsAccount()
|
Destructors |
Java does not have
destructors, but instead will invoke the finalize() member
function before an object is garbage collected. |
finalize()
|
Exceptions |
It is generally accepted to
use the letter . e. to represent exceptions. |
e
|
Final static fields
(constants) |
Use all uppercase letters
with the words separated by underscores. A better approach is to use
final static getter member functions because it greatly increases
flexibility. |
MIN_BALANCE, DEFAULT_DATE
|
Getter member functions |
Prefix the name of the field
being accessed with . get.. |
getFirstName(), getLastName(),
getWarpSpeeed()
|
Interfaces |
Use a full English
description describing the concept that the interface encapsulates, with
the first letters of all words capitalized. It is customary to postfix
the name with either . able,. . ible,. or . er. but this is not
required. |
Runnable, Contactable,
Prompter, Singleton
|
Local variables |
Use full English
descriptions with the first letter in lower case but do not hide
existing fields/fields. For example, if you have a field named .
firstName. do not have a local variable called . firstName.. |
grandTotal, customer,
newAccount
|
Loop counters |
It is generally accepted to
use the letters i, j, or k, or the name . counter.. |
i, j, k, counter
|
Packages |
Use full English
descriptions, using mixed case with the first letter of each word in
uppercase, everything else in lower case. For global packages, reverse
the name of your Internet domain and concatenate to this the package
name. |
java.awt,
com.ambysoft.www.
persistence.mapping
|
Member Functions |
Use a full English
description of what the member function does, starting with an active
verb whenever possible, with the first letter in lower case. |
openFile(), addAccount()
|
Setter member functions |
Prefix the name of the field
being accessed with . set. . |
setFirstName(), setLastName(),
setWarpSpeed()
|
A really good rule of thumb to follow regarding documentation is to ask
yourself if you have never seen the code before, what information would you
need to effectively understand the code in a reasonable amount of time.
General Concepts:
- Comments should add to the clarity of your code
- If your program is not worth documenting, it probably is not worth
running
- Avoid decoration, i.e. do not use banner-like comments
- Keep comments simple
- Write the documentation before you write the code
- Document why something is being done, not just what
The following chart describes the three types of Java comments and
suggested uses for them.
Comment Type |
Usage |
Example |
Documentation |
Use documentation comments
immediately before declarations of interfaces, classes, member
functions, and fields to document them. Documentation comments are
processed by javadoc, see below, to create external documentation
for a class. |
/**
Customer . A customer is any person or organization that we sell
services and products to.
@author S.W. Ambler
*/ |
C style |
Use C-style comments to
document out lines of code that are no longer applicable, but that you
want to keep just in case you users change their minds, or because you
want to temporarily turn it off while debugging. |
/*
This code was commented out by B.Gustafsson, June 4 1999 because it
was replaced by the preceding code. Delete it after two years if it is
still not applicable.
. . . (the source code )
*/ |
Single line |
Use single line comments
internally within member functions to document business logic, sections
of code, and declarations of temporary variables. |
// Apply a 5% discount to
all invoices
// over $1000 as defined by the Sarek
// generosity campaign started in
// Feb. of 1995. |
The following chart summarizes what to document regarding each portion of
Java code that you write.
Item |
What to Document |
Arguments/
parameters |
The type of the parameter
What it should be used for
Any restrictions or pre-conditions
Examples |
Fields/
fields/properties |
Its description
Document all applicable invariants
Examples
Concurrency issues
Visibility decisions |
Classes |
The purpose of the class
Known bugs
The development/maintenance history of the class
Document applicable invariants
The concurrency strategy |
Compilation units |
Each class/interface defined in
the class, including a brief description
The file name and/or identifying information
Copyright information |
Getter member function |
Document why lazy initialization
was used, if applicable |
Interfaces |
The purpose
How it should and should not be used |
Local variables |
Its use/purpose |
Member Functions . Documentation |
What and why the member function
does what it does
What a member function must be passed as parameters
What a member function returns
Known bugs
Any exceptions that a member function throws
Visibility decisions
How a member function changes the object
Include a history of any code changes
Examples of how to invoke the member function if appropriate
Applicable pre-conditions and
post-condition |
Member Functions . Internal
comments |
Control structures
Why, as well as what, the code does
Local variables
Difficult or complex code
The processing order |
Package |
The rationale for the package
The classes in the package |
There are many conventions and standards which are critical to the
maintainability and enhancability of your Java code. 99.9% of the time it is
more important to program for people, your fellow developers, than it is to
program for the machine. Making your code understandable to others is of
utmost importance.
Convention Target |
Convention |
Accessor member functions |
Consider using lazy
initialization for fields in the database
Use accessors for obtaining and modifying all fields
Use accessors for . constants"
For collections, add member functions to insert and remove items
Whenever possible, make accessors protected, not public |
Fields |
Fields should always be
declared private
Do not directly access fields, instead use accessor member functions
Do not use final static fields (constants), instead use accessor member
functions
Do not hide names
Always initialize static fields |
Classes |
Minimize the public and
protected interfaces
Define the public interface for a class before you begin coding it
Declare the fields and member functions of a class in the following
order:
- constructors
- finalize()
- public member functions
- protected member functions
- private member functions
- private field
|
Local variables |
Do not hide names
Declare one local variable per line of code
Document local variables with an inline comment
Declare local variables immediately before their use
Use local variables for one thing only |
Member Functions |
Document your code
Paragraph your code
Use whitespace, one line before control structures and two before
member function declarations
A member function should be understandable in less than thirty seconds
Write short, single command lines
Restrict the visibility of a member function as much as possible
Specify the order of operations |
[AMB98] |
Ambler, S.W. (1998). Building Object
Applications That Work: Your Step-By-Step Handbook for Developing Robust
Systems with Object Technology. New York: SIGS Books/Cambridge
University Press |
[COA97] |
Coad, P. and Mayfield, M. (1997). Java
Design: Building Better Apps & Applets. Upper Saddle River, NJ:
Prentice Hall Inc. |
[DES97] |
DeSoto, A. (1997). Using the Beans
Development Kit 1.0 February 1997: A Tutorial. Sun Microsystems. |
[GOS96] |
Gosling, J., Joy, B., Steele, G. (1996). The
Java Language Specification. Reading, MA: Addison Wesley Longman Inc. |
[GRA97] |
Grand, M. (1997). Java Language Reference.
Sebastopol, CA: O. Reilly & Associates, Inc. |
[KAN97] |
Kanerva, J. (1997). The Java FAQ.
Reading, MA: Addison Wesley Longman Inc. |
[KOE97] |
Koenig, A. (1997). The Importance . and
Hazards . of Performance Measurement. New York: SIGS Publications,
Journal of Object-Oriented Programming, January, 1997, 9(8), pp. 58-60. |
[LAF97] |
Laffra, C. (1997). Advanced Java: Idioms,
Pitfalls, Styles and Programming Tips. Upper Saddle River, NJ: Prentice
Hall Inc. |
[LEA97] |
Lea, D. (1997). Concurrent Programming in
Java: Design Principles and Patterns. Reading, MA: Addison Wesley
Longman Inc |
[MCO93] |
McConnell, S. (1993). Code Complete . A
Practical Handbook of Software Construction. Redmond, WA: Microsoft
Press. |
[MEY88] |
Meyer, B. (1988). Object-Oriented Software
Construction. Upper Saddle River, NJ: Prentice Hall Inc. |
[NAG95] |
Nagler, J. (1995). Coding Style and Good
Computing Practices. http://wizard.ucr.edu/~nagler/coding_style.html |
[SUN96] |
Sun Microsystems (1996). javadoc . The
Java API Documentation Generator. Sun Microsystems. |
[SUN97] |
Sun Microsystems (1997). 100% Pure Java
Cookbook for Java Developers . Rules and Hints for Maximizing the
Portability of Java Programs. Sun Microsystems. |
[VIS96] |
Vision 2000 CCS Package and Application Team
(1996). Coding Standards for C, C++, and Java.
http://v2ma09.gsfc.nasa.gov/coding_standards.html |
100% pure . Effectively a "seal of approval" from Sun that
says that a Java applet, application, or package, will run on ANY platform
which supports the Java VM.
Accessor . A member function that either modifies or returns the value
of a field. Also known as an access modifier. See getter and setter.
Analysis pattern . A modeling pattern that describes a solution to a
business/domain problem.
Antipattern . An approach to solving a common problem, an approach that
in time proves to be wrong or highly ineffective.
Argument . See parameter.
Field . A variable, either a literal data type or another object, that
describes a class or an instance of a class. Instance fields describe objects
(instances) and static fields describe classes. Fields are also referred to as
fields, field variables, and properties.
BDK . Beans development kit.
Block . A collection of zero or more statements enclosed in (curly)
braces.
Braces . The characters { and }, known as an open brace
and a close brace respectively, are used to define the beginning and end of a
block.
Class . A definition, or template, from which objects are instantiated.
Class testing . The act of ensuring that a class and its instances
(objects) perform as defined.
CMVC . Configuration Management and Version Control.
Compilation unit . A source code file, either a physical one on disk or
a "virtual" one stored in a database, in which classes and
interfaces are declared.
Component . An interface widget such as a list, button, or window.
Constant getter . A getter member function which returns the value of a
"constant," which may in turn be hard coded or calculated if need
be.
Constructor . A member function which performs any necessary
initialization when an object is created.
Containment . An object contains other objects that it collaborates
with to perform its behaviors. This can be accomplished either the use of
inner classes (JDK 1.1+) or the aggregation of instances of other classes
within an object (JDK 1.0+).
CPU . Central processing unit.
C-style comments . A Java comment format, /* & */, adopted from the
C/C++ language that can be used to create multiple-line comments. Commonly
used to "document out" unneeded or unwanted lines of code during
testing.
Design pattern . A modeling pattern that describes a solution to a
design problem.
Destructor . A C++ class member function that is used to remove an
object from memory once it is no longer needed. Because Java manages its own
memory, this kind of member function is not needed. Java does, however,
support a member function called finalize() that is similar in concept.
Documentation comments . A Java comment format, /** & */, that can
be processed by javadoc to provide external documentation for a class
file. The main documentation for interfaces, classes, member functions, and
fields should be written with documentation comments.
Field . See property.
finalize() . A member function that is automatically invoked during
garbage collection before an object is removed from memory. The purpose of
this member function is to do any necessary cleanup, such as the closing of
open files.
Garbage collection . The automatic management of memory where objects
that are no longer referenced are automatically removed from memory.
Getter . A type of accessor member function that returns the value of a
field. A getter can be used to answer the value of a constant, which is often
preferable to implementing the constant as a static field because this is a
more flexible approach.
HTML . Hypertext markup language, an industry-standard format for
creating web pages.
Indenting . See paragraphing.
Inline comments . The use of a line comment to document a line of
source code where the comment immediate follows the code on the same line as
the code. Single line comments are typically used for this, although C-style
comments can also be employed.
Interface . The definition of a common signature, including both member
functions and fields, which a class that implements an interface must support.
Interfaces promote polymorphism by composition.
I/O . Input/output.
Invariant . A set of assertions about an instance or class that must be
true at all "stable" times, the periods before and after the
invocation of a member function on the object/class.
Java . An industry-standard object-oriented development language that
is well-suited for developing applications for the Internet and applications
that must operate on a wide variety of computing platforms.
javadoc . A utility included in the JDK that processes a Java source
code file and produces an external document, in HTML format, describing the
contents of the source code file based on the documentation comments in the
code file.
JDK . Java Development Kit.
Lazy initialization . A technique in which a field is initialized in
its corresponding getter member function the first time that it is needed.
Lazy initialization is used when a field is not commonly needed and it either
requires a large amount of memory to store or it needs to be read in from
permanent storage.
Local variable . A variable that is defined within the scope of a
block, often a member function. The scope of a local variable is the block in
which it is defined.
Member Function . A piece of executable code that is associated with a
class, or the instances of a class. Think of a member function as
the object-oriented equivalent of a function.
Member Function signature . See signature.
Method testing . The act of ensuring that a member function (member
function) performs as defined.
Name hiding . This refers to the practice of using the same, or at
least similar, name for a field/variable/argument as for one of higher scope.
The most common abuse of name hiding is to name a local variable the same as
an instance field. Name hiding should be avoided as it makes your code harder
to understand and prone to bugs.
Overload . A member function is said to be overloaded when it is
defined more than once in the same class (or in a subclass), the only
difference being the signature of each definition.
Override . A member function is said to be overridden when it is
redefined in a subclass and it has the same signature as the original
definition.
Package . A collection of related classes.
Paragraphing . A technique where you indent the code within the scope
of a code block by one unit, usually a horizontal tab, so as to distinguish it
from the code outside of the code block. Paragraphing helps to increase the
readability of your code.
Parameter . An argument passed to a member function. A parameter may be
a defined type, such as a string or an int, or an object.
post-condition . A property or assertion that will be true after a
member function is finished running.
pre-condition . A constraint under which a member function will
function properly.
Property . See field.
Setter . An accessor member function that sets the value of a field.
Signature . The combination of the type of parameters, if any, and
their order that must be passed to a member function. Also called the member
function signature.
Single-line comments . A Java comment format, // & , adopted from
the C/C++ language that is commonly used for the internal member function
documentation of business logic.
Tags . A convention for marking specified sections of documentation
comments that will be processed by javadoc to produce
professional-looking comments. Examples of tags include @see and @author.
Test harness . A collection of member functions for testing your code
UML . Unified modeling language, an industry standard modeling
notation.
Visibility . A technique that is used to indicate the level of
encapsulation of a class, member function, or field. The keywords public,
protected, and private can be used to define visibility.
Whitespace . Blank lines, spaces, and tabs added to your code to
increase its readability.
Widget . See component.
Copyright
⌐ 1987 - 2000 Rational Software Corporation
| |

|